
window.onerrorx = function (message, url, code) {
    //Console.dumpError(message);
    error("SYSTEM ERROR!\n\t* " + message + "\n\t* at: " + url + ":" + code);
    Util.showStatusBarError("SYSTEM ERROR! * " + message + " at: " + url + ":" + code, true);
    return false;
};

export default class Pencil {
    public readonly SNAP: number = 10;
    public readonly UNSNAP: number = 10;

    private static booted: boolean = false;

    public static editorClasses: Array<any> = [];

    static registerEditor(editorClass: any) {
        this.editorClasses.push(editorClass);
    };
    public static sharedEditors: Array<any> = [];

    static registerSharedEditor(sharedEditor) {
        this.sharedEditors.push(sharedEditor);
    }

    static xferHelperClasses: Array<any> = [];
    static registerXferHelper(helperClass: any) {
        this.xferHelperClasses.push(helperClass);
    };

    public static behaviors: any = {};

    public static documentExporters: Array<any> = [];
    public static defaultDocumentExporter = null;

    static registerDocumentExporter(exporter: any, defaultExporter: boolean) {
        this.documentExporters.push(exporter);
        if (defaultExporter) this.defaultDocumentExporter = exporter;
    };
    static getDocumentExporterById(id: number) {
        for (var i = 0; i < this.documentExporters.length; i ++) {
            if (this.documentExporters[i].id == id) {
                return this.documentExporters[i];
            }
        }
        return null;
    };

    static toggleHeartBeat(): void {
        if (this.window.hasAttribute("class")) {
            this.window.removeAttribute("class");
        } else {
            this.window.setAttribute("class", "Beat");
        }
        window.setTimeout(this.toggleHeartBeat, 200);
    };

    static installEditors(canvas: any): void {
        for (const factory in this.editorClasses) {
            const constructorFunction = this.editorClasses[factory];
            const editor = new constructorFunction();
            editor.install(canvas);
        }
    };
    static installXferHelpers(canvas: any): void {
        for (const factory in this.xferHelperClasses) {
            const constructorFunction = this.xferHelperClasses[factory];
            const helper = new constructorFunction(canvas);
            canvas.xferHelpers.push(helper);
        }
    };
    static fixUI(): void {
        Dom.workOn(".//xul:*[@image]", this.window, function (node) {
            var image = node.getAttribute("image");
            if (image.match(/^moz\-icon:\/\/([^\?]+)\?size=([a-z]+)$/)) {
                var src = "Icons/MozIcons/" + RegExp.$1 + "-" + RegExp.$2 + ".png";
                node.setAttribute("image", src);
            }
        });
    };
    static boot = function (event): void {
        try {
            if (this.booted) return;

            debug("BOOT: Initializing Pencil core");

            this.app = require('electron').remote.app;

            this.booted = true;
            this.window = document.documentElement;
            this.rasterizer = new Rasterizer("image/png");

            debug("BOOT:   Loading stencils");
            CollectionManager.loadStencils();
            debug("BOOT:   Loading export templates");
            ExportTemplateManager.loadTemplates();
            debug("BOOT:   Configuring export manager");
            this.documentExportManager = new DocumentExportManager();

            this.activeCanvas = null;
            debug("BOOT:   Setting up UI commands");
            this.setupCommands();

            this.undoMenuItem = document.getElementById("editUndoMenu");
            this.redoMenuItem = document.getElementById("editRedoMenu");

            this.sideBoxFloat = document.getElementById("sideBoxFloat");
            var collectionPaneSizeGrip = document.getElementById("collectionPaneSizeGrip");

            debug("BOOT:   Registering global event handlers");
            debug("BOOT:     - Collection pane collapsing event");
            window.addEventListener("mousedown", function (event) {
                var target = event.target;
                if (target.className && target.className == "CollectionPane") {
                    if (Pencil.hideCollectionPaneTimer) {
                        clearTimeout(Pencil.hideCollectionPaneTimer);
                        Pencil.hideCollectionPaneTimer = null;
                    }

                    if (target.id == "collectionPaneSizeGrip") {
                        collectionPaneSizeGrip._oX = event.clientX;
                        collectionPaneSizeGrip._oY = event.clientY;

                        collectionPaneSizeGrip._width = Pencil.sideBoxFloat.getBoundingClientRect().width;
                        collectionPaneSizeGrip._height = Pencil.sideBoxFloat.getBoundingClientRect().height;

                        collectionPaneSizeGrip._hold = true;
                    }
                } else {
                    if (Pencil.isCollectionPaneVisibled()) {
                        Pencil.hideCollectionPane();
                    }
                }
            }, true);

            // document.body.onscroll = function (event) {
            //     if (document.body.scrollTop != 0) {
            //         document.body.scrollTop = 0;
            //     }
            // };

            debug("BOOT:     - Global scroll event");
            document.addEventListener("scroll", function (event) {
                if (document.body.scrollTop != 0 && event.target === document) {
                    document.body.scrollTop = 0;
                }
            }, false);

            debug("BOOT:     - Booting shared editors.");
            //booting shared editors
            for (var i in Pencil.sharedEditors) {
                try {
                    debug("BOOT:         " + Pencil.sharedEditors[i].constructor.name);
                    Pencil.sharedEditors[i].setup();
                } catch (e) {
                    Console.dumpError(e, "stdout");
                }
            }

            debug("BOOT:     - p:CanvasChanged event.");
            document.documentElement.addEventListener("p:CanvasChanged", Pencil.handleCanvasChange, false);
            debug("BOOT:     - p:TargetChanged event.");
            document.documentElement.addEventListener("p:TargetChanged", Pencil.handleTargetChange, false);

            debug("BOOT:     - p:ContentModified event.");
            document.documentElement.addEventListener("p:ContentModified", Pencil._setupUndoRedoCommand, false);
            debug("BOOT:     - p:UserFontLoaded event.");
            document.documentElement.addEventListener("p:UserFontLoaded", function () {
                if (ApplicationPane._instance) ApplicationPane._instance.sharedFontEditor.reloadFontItems();
            }, false);

            debug("BOOT:     - Fallback scroll event.");
            document.body.onscroll = function (event) {
                if (document.body.scrollTop != 0) {
                    document.body.scrollTop = 0;
                }
            };
            debug("BOOT:   Done initializing Pencil core.");
        } catch (e) {
            console.error(e);
        }
    };
    static handleArguments = function() {
        var remote = require('electron').remote;
        var appArguments = remote.getGlobal('sharedObject').appArguments;
        if (appArguments && appArguments.length > 1) {
            var arg = appArguments[1];
            if (arg != "app" && arg != "./app") {
                this.documentHandler.loadDocumentFromArguments(arg);
            }
        }
    };
    static setTitle(s) {
        document.title = s + " - Pencil";
    };

    static handleCanvasChange(event) {
        this.activeCanvas = event.canvas;
        this.setupCommands();
        this.invalidateSharedEditor();
    };
    static handleTargetChange(event) {
        this.setupCommands();
        this.invalidateSharedEditor();
    };
    static invalidateSharedEditor() {
        var canvas = this.activeCanvas;
        var target = canvas ? canvas.currentController : null;

        if (!target) {
            for (var i in this.sharedEditors) {
                try {
                    this.sharedEditors[i].detach();
                } catch (e) {
                    Console.dumpError(e, "stdout");
                }
            }
            return;
        }
        for (var i in this.sharedEditors) {
            try {
                this.sharedEditors[i].attach(target);
            } catch (e) {
                Console.dumpError(e, "stdout");
            }
        }
    };
    static setPainterCommandChecked(v) {
        var painterButton = this.formatPainterButton;
        if (painterButton) {
            // painterCommand.checked = v;

            if (!v) {
                document.body.removeAttribute("format-painter");
                // var canvasList = Pencil.getCanvasList();
                // for (var i = 0; i < canvasList.length; i++) {
                //     Dom.removeClass(canvasList[i], "Painter");
                // }
                painterButton.removeAttribute("checked");
            } else {
                painterButton.setAttribute("checked", "true");
            }
        }
    };
    static getCanvasList() {
        var r = [];
        Dom.workOn("//xul:pcanvas", document.documentElement, function (node) {
            r.push(node);
        });
        return r;
    };
    static setupCommands() {

    };
    private static _setupUndoRedoCommand(): void {
        var canvas = this.activeCanvas;

        this._enableCommand("undoCommand", canvas && canvas.careTaker && canvas.careTaker.canUndo());
        this._enableCommand("redoCommand", canvas && canvas.careTaker && canvas.careTaker.canRedo());

        if (canvas && canvas.careTaker) {
            var currentAction = canvas.careTaker.getCurrentAction();
            var prevAction = canvas.careTaker.getPrevAction();
            if (canvas.careTaker.canUndo() && canvas.careTaker.canRedo()) {
                Pencil.updateUndoRedoMenu(currentAction, prevAction);
            } else if (canvas.careTaker.canUndo()) {
                Pencil.updateUndoRedoMenu(currentAction, "");
            } else {
                Pencil.updateUndoRedoMenu("", prevAction);
            }
        }
    };
    private static _enableCommand(name, condition) {
        var command = document.getElementById(name);
        if (command) {
            if (condition) {
                command.removeAttribute("disabled");
            } else {
                command.setAttribute("disabled", true);
            }
        }
    };

    static getGridSize(): { w: number, h: number } {
        var size = Config.get("edit.gridSize");
        if (size == null) {
            size = 5;
            Config.set("edit.gridSize", size);
        }
        return {w: size, h: size};
    };

    static getGridStyle(): string {
        var style = Config.get("edit.gridStyle");
        if (style == null) {
            style = "Dotted";
            Config.set("edit.gridStyle", style);
        }
        return style;
    };

    public static getCurrentTarget(): any {
        var canvas = this.activeCanvas;
        return canvas ? canvas.currentController : null;
    };
    public static isCollectionPaneVisibled(): boolean {
        return false;
    }
    private static _hideCollectionPane(c: number): void {
        if (c <= 0) {
            this.sideBoxFloat.style.display = "none";
            this.hideCollectionPaneTimer = null;
            this.setUpSizeGrip();
        } else {
            this.sideBoxFloat.style.opacity = c;
            window.setTimeout("Pencil._hideCollectionPane(" + parseFloat(c - 0.5) + ")", 1);
        }
    };
    public static hideCollectionPane(): void {
        if (!this.hideCollectionPaneTimer) {
            if (Util.platform == "Linux") {
                this.hideCollectionPaneTimer = window.setTimeout("Pencil._hideCollectionPane(0)", 1);
            } else {
                this.hideCollectionPaneTimer = window.setTimeout("Pencil._hideCollectionPane(1)", 300);
            }
        }
    }
    public static setUpSizeGrip(): void {
        var box = this.sideBoxFloat.getBoundingClientRect();
        var sizeGrip = document.getElementById("collectionPaneSizeGrip");
        sizeGrip.setAttribute("left", (box.width - 15));
        sizeGrip.setAttribute("top", (box.height - 19));
        sizeGrip.style.display = Pencil.isCollectionPaneVisibled() ? '' : "none";
    };
    private static _showCollectionPane(c: number): void {
        if (c == 0) {
            this.sideBoxFloat.style.opacity = 0;
            this.sideBoxFloat.style.display = "";
            this.setUpSizeGrip();
        }
        if (c <= 1) {
            this.sideBoxFloat.style.opacity = c;
            window.setTimeout("Pencil._showCollectionPane(" + parseFloat(c + 0.5) + ")", 1);
        }
    };
    public static showCollectionPane(): void {
        if (Util.platform == "Linux") {
            this.sideBoxFloat.style.opacity = 1;
            this.sideBoxFloat.style.display = "";
            this.setUpSizeGrip();
        } else {
            this._showCollectionPane(0);
        }
    };
    public static toggleCollectionPane(dockable): void {
        if (!dockable) {
            if (Config.get("collectionPane.floating") == true) {
                if (this.isCollectionPaneVisibled()) {
                    if (Util.platform == "Linux") {
                        this._hideCollectionPane(0);
                    } else {
                        this._hideCollectionPane(1);
                    }
                } else {
                    this.showCollectionPane();
                }
            }
        } else {
            if (!Config.get("collectionPane.floating")) {
                Config.set("collectionPane.floating", true);
                document.getElementById("sideBox").style.display = "none";
                this.collectionPane = document.getElementById("collectionPane");
                this.privateCollectionPane = document.getElementById("privateCollectionPane");
                this.collectionPane.reloadCollections();
                this.privateCollectionPane.reloadCollections();
            } else {
                this._hideCollectionPane(0);
                Config.set("collectionPane.floating", false);
                document.getElementById("sideBox").style.display = "";
                this.collectionPane = document.getElementById("_collectionPane");
                this.privateCollectionPane = document.getElementById("_privateCollectionPane");
                this.collectionPane.reloadCollections();
                this.privateCollectionPane.reloadCollections();
            }

            document.getElementById("floatingCollectionPane").setAttribute("checked", Config.get("collectionPane.floating") == false);
        }
    };
    public static handlePropertiesCommand(): void {
        if (this.activeCanvas.currentController) {
            this.activeCanvas._showPropertyDialog();
        } else {
            if (!this.controller._pageToEdit) {
                this.controller._pageToEdit = this.controller.getCurrentPage();
            }

            this.controller.editPageProperties(this.controller._pageToEdit);
            this.controller._pageToEdit = null;
        }
    };
    public static updateUndoRedoMenu(currentAction, prevAction): void {
//    Pencil.undoMenuItem.setAttribute("label", Util.getMessage("menu.undo.label") + currentAction);
//    Pencil.redoMenuItem.setAttribute("label", Util.getMessage("menu.redo.label") + prevAction);
        this.activeCanvas.updateContextMenu(currentAction, prevAction);
    };
    private static _getCanvasPadding(): number {
        return 10;
    };
}

pencilSandbox.Pencil = Pencil;


Object.defineProperty(Pencil, "activeCanvas", {
    set: function (canvas) {
        Canvas.activeCanvas = canvas;
    },
    get: function () {
        return Canvas.activeCanvas;
    }
});
